package net.xcrane.xmpp.tools.ui;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;

import org.jivesoftware.smack.ExceptionCallback;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry;
import org.jivesoftware.smack.roster.RosterListener;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.muc.MultiUserChatManager;
import org.jivesoftware.smackx.ping.PingManager;
import org.jivesoftware.smackx.privacy.PrivacyList;
import org.jivesoftware.smackx.privacy.PrivacyListManager;
import org.jivesoftware.smackx.privacy.packet.PrivacyItem;
import org.jivesoftware.smackx.privacy.packet.PrivacyItem.Type;
import org.jivesoftware.smackx.snyc.packet.APNSToken;
import org.jivesoftware.smackx.snyc.packet.CancelAPNS;
import org.jivesoftware.smackx.snyc.packet.Disturber;
import org.jivesoftware.smackx.snyc.packet.Fin;
import org.jivesoftware.smackx.snyc.packet.OMAmount;
import org.jivesoftware.smackx.snyc.packet.OfflineMessageItems;
import org.jivesoftware.smackx.snyc.packet.OfflineMsgAmount;
import org.jivesoftware.smackx.snyc.packet.OfflineMsgPage;
import org.jivesoftware.smackx.snyc.packet.QuitRoomExtensionElement;
import org.jivesoftware.smackx.snyc.packet.RedEnvelopeElment;
import org.jivesoftware.smackx.xdata.Form;
import org.jivesoftware.smackx.xdata.FormField;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Resourcepart;

public class SmackFrame {

	private JFrame frmXmppTools;
	private JTextField txtName;
	private JTextField txtPwd;
	private JTextField txtHost;
	private JTextField txtPort;

	private JTextArea txtMsg = null;
	private JTextArea txtChat = null;

	private XMPPTCPConnection xmppCnn = null;

	private Roster roster;

	private JTextField txtTo;
	private JTextField txtStatus;

	private JScrollPane spMsg = null;

	private JTextField txtDomain;
	private JTextField txtGroup;
	private JTextField txtResource;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					SmackFrame window = new SmackFrame();
					window.frmXmppTools.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public SmackFrame() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frmXmppTools = new JFrame();
		frmXmppTools.setTitle("XMPP Tools");
		frmXmppTools.setBounds(100, 100, 953, 698);
		frmXmppTools.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frmXmppTools.getContentPane().setLayout(null);

		JLabel lblName = new JLabel("Name:");
		lblName.setBounds(40, 38, 86, 30);
		frmXmppTools.getContentPane().add(lblName);

		txtName = new JTextField();
		txtName.setText("snowing");
		txtName.setBounds(140, 38, 155, 30);
		frmXmppTools.getContentPane().add(txtName);
		txtName.setColumns(10);

		JLabel labelPwd = new JLabel("Password:");
		labelPwd.setBounds(364, 38, 86, 30);
		frmXmppTools.getContentPane().add(labelPwd);

		txtPwd = new JTextField();
		txtPwd.setText("snowing");
		txtPwd.setColumns(10);
		txtPwd.setBounds(464, 38, 155, 30);
		frmXmppTools.getContentPane().add(txtPwd);

		JLabel lblHost = new JLabel("Host:");
		lblHost.setBounds(40, 73, 86, 30);
		frmXmppTools.getContentPane().add(lblHost);

		txtHost = new JTextField();
		txtHost.setText("localhost");
		txtHost.setColumns(10);
		txtHost.setBounds(140, 74, 155, 30);
		frmXmppTools.getContentPane().add(txtHost);

		JLabel lblPort = new JLabel("Port:");
		lblPort.setBounds(364, 73, 86, 30);
		frmXmppTools.getContentPane().add(lblPort);

		txtPort = new JTextField();
		txtPort.setText("5222");
		txtPort.setColumns(10);
		txtPort.setBounds(464, 73, 155, 30);
		frmXmppTools.getContentPane().add(txtPort);

		JLabel lblChat = new JLabel("Chat:");
		lblChat.setBounds(40, 245, 72, 18);
		frmXmppTools.getContentPane().add(lblChat);

		JScrollPane spChat = new JScrollPane();
		spChat.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		spChat.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		spChat.setBounds(140, 242, 577, 88);
		frmXmppTools.getContentPane().add(spChat);

		txtChat = new JTextArea();
		txtChat.setLineWrap(true);
		spChat.setViewportView(txtChat);

		JLabel lblMsg = new JLabel("Message:");
		lblMsg.setBounds(40, 333, 72, 18);
		frmXmppTools.getContentPane().add(lblMsg);

		spMsg = new JScrollPane();
		spMsg.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		spMsg.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
		spMsg.setBounds(140, 343, 577, 303);
		frmXmppTools.getContentPane().add(spMsg);

		txtMsg = new JTextArea();
		txtMsg.setLineWrap(true);
		spMsg.setViewportView(txtMsg);

		JButton btnLogon = new JButton("Logon");
		btnLogon.addActionListener(new LogonAction());
		btnLogon.setBounds(789, 14, 134, 27);
		frmXmppTools.getContentPane().add(btnLogon);

		JButton btnLogout = new JButton("Logout");
		btnLogout.addActionListener(new LogoutAction(frmXmppTools));
		btnLogout.setBounds(789, 41, 134, 27);
		frmXmppTools.getContentPane().add(btnLogout);

		JButton btnSendMsg = new JButton("Send Message");
		btnSendMsg.addActionListener(new SendAction());
		btnSendMsg.setBounds(789, 92, 143, 30);
		frmXmppTools.getContentPane().add(btnSendMsg);

		JLabel lblTo = new JLabel("To:");
		lblTo.setBounds(40, 112, 86, 30);
		frmXmppTools.getContentPane().add(lblTo);

		txtTo = new JTextField();
		txtTo.setText("ximen");
		txtTo.setColumns(10);
		txtTo.setBounds(140, 112, 155, 30);
		frmXmppTools.getContentPane().add(txtTo);

		JLabel lblStatus = new JLabel("Status");
		lblStatus.setBounds(364, 108, 86, 30);
		frmXmppTools.getContentPane().add(lblStatus);

		txtStatus = new JTextField();
		txtStatus.setText("leave");
		txtStatus.setColumns(10);
		txtStatus.setBounds(464, 108, 155, 30);
		frmXmppTools.getContentPane().add(txtStatus);

		spMsg.setAutoscrolls(true);

		JButton btnClose = new JButton("Close");
		btnClose.addActionListener(new CloseAction());
		btnClose.setBounds(789, 65, 143, 27);
		frmXmppTools.getContentPane().add(btnClose);

		JLabel lblDomain = new JLabel("Domain:");
		lblDomain.setBounds(40, 150, 86, 30);
		frmXmppTools.getContentPane().add(lblDomain);

		txtDomain = new JTextField();
		txtDomain.setText("sun");
		txtDomain.setColumns(10);
		txtDomain.setBounds(140, 150, 155, 30);
		frmXmppTools.getContentPane().add(txtDomain);

		JButton btnClear = new JButton("Clear");
		btnClear.addActionListener(new ClearAction());
		btnClear.setBounds(789, 291, 143, 27);
		frmXmppTools.getContentPane().add(btnClear);

		JButton btnFin = new JButton("Fin");
		btnFin.addActionListener(new FinAction());
		btnFin.setBounds(789, 213, 134, 27);
		frmXmppTools.getContentPane().add(btnFin);

		JLabel lblGroup = new JLabel("Group:");
		lblGroup.setBounds(364, 147, 86, 30);
		frmXmppTools.getContentPane().add(lblGroup);

		txtGroup = new JTextField();
		txtGroup.setText("room1");
		txtGroup.setColumns(10);
		txtGroup.setBounds(464, 147, 155, 30);
		frmXmppTools.getContentPane().add(txtGroup);

		JButton btnSendGroupchat = new JButton("Send Group Msg");
		btnSendGroupchat.addActionListener(new SendGroupAction());
		btnSendGroupchat.setBounds(789, 330, 143, 27);
		frmXmppTools.getContentPane().add(btnSendGroupchat);

		JButton btnCreateRoom = new JButton("Create Room");
		btnCreateRoom.addActionListener(new CreateRoomAction());
		btnCreateRoom.setBounds(789, 379, 143, 27);
		frmXmppTools.getContentPane().add(btnCreateRoom);

		JButton btnChangeNick = new JButton("Change Nick");
		btnChangeNick.addActionListener(new ChangeNickAction());
		btnChangeNick.setBounds(789, 404, 143, 27);
		frmXmppTools.getContentPane().add(btnChangeNick);

		JButton btnPresenceRoom = new JButton("Presence Room");
		btnPresenceRoom.addActionListener(new PresenceRoomAction());
		btnPresenceRoom.setBounds(789, 353, 143, 27);
		frmXmppTools.getContentPane().add(btnPresenceRoom);

		JButton btnOMAmount = new JButton("OM Amount");
		btnOMAmount.addActionListener(new OmAmountAction());
		btnOMAmount.setBounds(789, 241, 134, 27);
		frmXmppTools.getContentPane().add(btnOMAmount);

		JButton btnOMPage = new JButton("OM Page");
		btnOMPage.addActionListener(new OmPageAction());
		btnOMPage.setBounds(789, 269, 134, 27);
		frmXmppTools.getContentPane().add(btnOMPage);

		JButton btnDestoryRoom = new JButton("Destory Room");
		btnDestoryRoom.addActionListener(new DestoryRoomAction());
		btnDestoryRoom.setBounds(789, 454, 143, 27);
		frmXmppTools.getContentPane().add(btnDestoryRoom);

		JButton butQuitRoom = new JButton("Quit From Room");
		butQuitRoom.addActionListener(new QuitRoomAction());
		butQuitRoom.setBounds(789, 160, 143, 27);
		frmXmppTools.getContentPane().add(butQuitRoom);

		JButton btnGetJoinedRooms = new JButton("Get Joined Rooms");
		btnGetJoinedRooms.addActionListener(new GetJoinedRoomsAction());
		btnGetJoinedRooms.setBounds(789, 428, 143, 27);
		frmXmppTools.getContentPane().add(btnGetJoinedRooms);

		JButton btnRedEnvelope = new JButton("Red Envelope");
		btnRedEnvelope.addActionListener(new RedEnvelopeAction());
		btnRedEnvelope.setBounds(789, 185, 143, 27);
		frmXmppTools.getContentPane().add(btnRedEnvelope);

		JButton btnAddPrivacy = new JButton("Add Privacy");
		btnAddPrivacy.addActionListener(new AddPrivacyAction());
		btnAddPrivacy.setBounds(634, 40, 143, 30);
		frmXmppTools.getContentPane().add(btnAddPrivacy);

		JButton btnDeletePrivacy = new JButton("Delete Privacy");
		btnDeletePrivacy.addActionListener(new DeletePrivacyAction());
		btnDeletePrivacy.setBounds(634, 63, 143, 30);
		frmXmppTools.getContentPane().add(btnDeletePrivacy);

		JButton btnGetPrivacy = new JButton("Get Privacy");
		btnGetPrivacy.addActionListener(new GetPrivacyAction());
		btnGetPrivacy.setBounds(634, 105, 143, 30);
		frmXmppTools.getContentPane().add(btnGetPrivacy);

		JButton btnGetRoster = new JButton("Get Roster");
		btnGetRoster.addActionListener(new GetRosterAction());
		btnGetRoster.setBounds(634, 129, 143, 30);
		frmXmppTools.getContentPane().add(btnGetRoster);

		JButton btnAddRosterItem = new JButton("Add Roster Item");
		btnAddRosterItem.addActionListener(new AddRosterItemAction());
		btnAddRosterItem.setBounds(634, 158, 143, 30);
		frmXmppTools.getContentPane().add(btnAddRosterItem);

		JButton btnSendWithResponse = new JButton("Send With RSP");
		btnSendWithResponse.addActionListener(new SendWithResponseAction());
		btnSendWithResponse.setBounds(789, 118, 143, 30);
		frmXmppTools.getContentPane().add(btnSendWithResponse);

		JButton btnSetApnstoken = new JButton("Set APNSToken");
		btnSetApnstoken.addActionListener(new SetTokenAction());
		btnSetApnstoken.setBounds(634, 184, 143, 30);
		frmXmppTools.getContentPane().add(btnSetApnstoken);

		JLabel lblResource = new JLabel("Resource:");
		lblResource.setBounds(40, 188, 86, 30);
		frmXmppTools.getContentPane().add(lblResource);

		txtResource = new JTextField();
		txtResource.setText("XMPP-Tools");
		txtResource.setColumns(10);
		txtResource.setBounds(140, 188, 155, 30);
		frmXmppTools.getContentPane().add(txtResource);

		JButton btnCancelApns = new JButton("Cancel APNS");
		btnCancelApns.addActionListener(new CancelAPNSAction());
		btnCancelApns.setBounds(634, 211, 143, 30);
		frmXmppTools.getContentPane().add(btnCancelApns);

		JButton btnSetupDisturber = new JButton("Setup Disturber");
		btnSetupDisturber.addActionListener(new SetupDisturberAction());
		btnSetupDisturber.setBounds(789, 480, 143, 27);
		frmXmppTools.getContentPane().add(btnSetupDisturber);

		JButton btnGetDisturberList = new JButton("Get Disturber List");
		btnGetDisturberList.addActionListener(new GetDisturberListAction());
		btnGetDisturberList.setBounds(789, 506, 143, 27);
		frmXmppTools.getContentPane().add(btnGetDisturberList);

		JButton btnAddFriend = new JButton("Add Friend");
		btnAddFriend.addActionListener(new AddFriendAction());
		btnAddFriend.setBounds(789, 569, 143, 27);
		frmXmppTools.getContentPane().add(btnAddFriend);
	}

	private void log(String str) {

		SwingUtilities.invokeLater(new LogUpdateRunner(str));

	}

	class LogUpdateRunner implements Runnable {

		private String log = null;

		LogUpdateRunner(String log) {
			this.log = log;
		}

		public void run() {
			txtMsg.append(new Date() + " - " + log + "\r\n");
			txtMsg.append("\r\n");

			JScrollBar vertical = spMsg.getVerticalScrollBar();
			vertical.setValue(vertical.getMaximum());
		}
	}

	class LogonAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			PingManager.setDefaultPingInterval(6000);
			Roster.setRosterLoadedAtLoginDefault(false);

			// Create a connection to the jabber.org server on a specific port.
			XMPPTCPConnectionConfiguration config = null;

			try {
				config = XMPPTCPConnectionConfiguration.builder().setDebuggerEnabled(true)
						.setXmppDomain(txtDomain.getText()).setHostAddress(InetAddress.getByName(txtHost.getText()))
						.setPort(Integer.valueOf(txtPort.getText()).intValue())
						.setSecurityMode(XMPPTCPConnectionConfiguration.SecurityMode.disabled)
						.setSendPresence(false)

						.addEnabledSaslMechanism(SASLMechanism.PLAIN)
//						.setResource("XMPP-Tools")
						.setResource(txtResource.getText()).setConnectTimeout(600 * 1000)
//						.setCompressionEnabled(true)
//						.setSocketFactory(new DummySSLSocketFactory())
						.build();

				xmppCnn = new XMPPTCPConnection(config);
				xmppCnn.setReplyTimeout(600 * 1000);
				xmppCnn.setUseStreamManagement(false);
				xmppCnn.addAsyncStanzaListener(new IncomeingPacketListener(), null);
				xmppCnn.addPacketSendingListener(new OutcomingPacketInterceptor(), null);

				roster = Roster.getInstanceFor(xmppCnn);
//				roster.setRosterLoadedAtLogin(false);
				roster.setSubscriptionMode(Roster.SubscriptionMode.manual);

				xmppCnn.connect();
				xmppCnn.login(txtName.getText(), txtPwd.getText());
			} catch (Exception e1) {
				log(e1.getMessage());
			}

			Presence presence = new Presence(Presence.Type.available);
			presence.setStatus("I am chatting");
			try {
				xmppCnn.sendStanza(presence);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class LogoutAction implements ActionListener {
		JFrame frame = null;

		public LogoutAction(JFrame frame) {
			this.frame = frame;
		}

		public void actionPerformed(ActionEvent e) {
			Presence presence = new Presence(Presence.Type.unavailable);
			presence.setStatus("offline");

			// Send the packet (assume we have a XMPPConnection instance called "xmppCnn").
			try {
				xmppCnn.disconnect(presence);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}

		}
	}

	class CloseAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			frmXmppTools.dispose();
		}
	}

	class SendAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			Message newMessage = new Message();
			newMessage.setType(Message.Type.chat);
			newMessage.setBody(txtChat.getText());

			try {
				newMessage.setTo(JidCreate.entityBareFrom(txtTo.getText() + "@" + txtDomain.getText()));
				newMessage.setFrom(JidCreate.entityBareFrom(txtName.getText() + "@" + txtDomain.getText()));

				xmppCnn.sendStanza(newMessage);

			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class SendWithResponseAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			Message newMessage = new Message();
			newMessage.setType(Message.Type.chat);
			newMessage.setBody(txtChat.getText());

			try {
				newMessage.setTo(JidCreate.entityBareFrom(txtTo.getText() + "@" + txtDomain.getText()));
				newMessage.setFrom(JidCreate.entityBareFrom(txtName.getText() + "@" + txtDomain.getText()));

				xmppCnn.sendStanzaWithResponseCallback(newMessage, new MessageIDFilter(newMessage),
						new MessageResponseListener(newMessage), new MessageExceptionCallback(), 5 * 1000);

			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class MessageIDFilter implements StanzaFilter {
		private Message message;

		MessageIDFilter(Message message) {
			this.message = message;
		}

		public boolean accept(Stanza stanza) {
			return message.getStanzaId().equals(stanza.getStanzaId());
		}
	};

	class MessageResponseListener implements StanzaListener {
		private Message message;

		MessageResponseListener(Message message) {
			this.message = message;
		}

		public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
			if (packet instanceof Message) {
				Message msg = (Message) packet;
				msg.getError();
				log("the message : [" + message.toXML() + "] ,\n the responsed message : [" + msg.toXML() + "]");
			}
		}
	}

	class MessageExceptionCallback implements ExceptionCallback {

		public void processException(Exception exception) {
			log("waitting message response ang get the exeption : " + exception);
		}

	}

	class AddPrivacyAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {

			// Set the name of the list_
			String listName = "public";

			// Create the list of PrivacyItem that will allow or deny some privacy aspect_
			String user = txtTo.getText() + "@" + txtDomain.getText();
//			String groupName = "enemies";
			ArrayList<PrivacyItem> privacyItems = new ArrayList<PrivacyItem>();

			PrivacyItem item = new PrivacyItem(Type.jid, user, false, 1);
			item.isFilterEverything();

			privacyItems.add(item);

//			user = "tsung2@sun";
//			item = new PrivacyItem(Type.jid, user, false, 1);
//			item.isFilterEverything();
//			privacyItems.add(item);

//			user = "tsung3@sun";
//			item = new PrivacyItem(Type.jid, user, false, 1);
//			item.isFilterEverything();
//			privacyItems.add(item);

//			item = new PrivacyItem(PrivacyItem.Type.subscription, PrivacyItem.SUBSCRIPTION_BOTH, true, 2);
//			privacyItems.add(item);

//			item = new PrivacyItem(PrivacyItem.Type.group, groupName, false, 3);
//			item.setFilterMessage(true);
//			privacyItems.add(item);

			// Get the privacy manager for the current connection._
			PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(xmppCnn);
			// Create the new list._
			try {
				privacyManager.createPrivacyList(listName, privacyItems);
				privacyManager.setDefaultListName(listName);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class GetPrivacyAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {

			PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(xmppCnn);
			// Retrieve server privacy lists_
			PrivacyList lists = null;

			try {
				lists = privacyManager.getDefaultList();
				log(lists.toString());
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class DeletePrivacyAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			PrivacyListManager privacyManager = PrivacyListManager.getInstanceFor(xmppCnn);
			// Retrieve server privacy lists_
			try {
				privacyManager.deletePrivacyList("public");
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class GetRosterAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {

//			Roster roster = Roster.getInstanceFor(xmppCnn);

			try {
				roster.reload();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
				log("ERR - " + e1.getMessage());
			}

//			roster.setRosterLoadedAtLogin(false);
			roster.setSubscriptionMode(Roster.SubscriptionMode.manual);

			Collection<RosterEntry> entries = roster.getEntries();
			if (entries == null || entries.isEmpty()) {
				log("------ <NO ROSTER> ------");
			} else {
				for (RosterEntry entry : entries) {
					log("<ROSTER> - " + entry.toString());
				}
			}

			roster.addRosterListener(new RosterListener() {
				public void presenceChanged(Presence presence) {
					log("Presence changed: " + presence.getFrom() + " - " + presence);
				}

				public void entriesAdded(Collection<Jid> addresses) {
					for (Jid entry : addresses) {
						log("entriesAdded - " + entry.toString());
					}
				}

				public void entriesUpdated(Collection<Jid> addresses) {
					for (Jid entry : addresses) {
						log("entriesUpdated - " + entry.toString());
					}
				}

				public void entriesDeleted(Collection<Jid> addresses) {
					for (Jid entry : addresses) {
						log("entriesDeleted - " + entry.toString());
					}
				}
			});
		}
	}

	class AddRosterItemAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			Roster roster = Roster.getInstanceFor(xmppCnn);

			try {
				roster.createEntry(JidCreate.entityBareFrom(txtTo.getText().trim() + "@" + txtDomain.getText()),
						txtTo.getText().trim(), null);
			} catch (Exception e1) {
				log(e1.getMessage());
			}
		}
	}

	class RedEnvelopeAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			Message newMessage = new Message();
			newMessage.setType(Message.Type.chat);

			RedEnvelopeElment redEnvelope = new RedEnvelopeElment();
			redEnvelope.setId("11");
			redEnvelope.setFrom(txtName.getText());
			redEnvelope.setTo(txtTo.getText());
			redEnvelope.setAmount("50");
			newMessage.addExtension(redEnvelope);

			try {
				newMessage.setTo(JidCreate.entityBareFrom(txtTo.getText() + "@" + txtDomain.getText()));
				newMessage.setFrom(JidCreate.entityBareFrom(txtName.getText() + "@" + txtDomain.getText()));

				xmppCnn.sendStanza(newMessage);

			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class QuitRoomAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			Message newMessage = new Message();
			newMessage.setType(Message.Type.groupchat);

			try {
				newMessage.setTo(JidCreate.entityBareFrom(txtGroup.getText() + "@conference." + txtDomain.getText()));
				newMessage.setFrom(JidCreate.entityBareFrom(txtName.getText() + "@" + txtDomain.getText()));
				newMessage.addExtension(new QuitRoomExtensionElement());

				xmppCnn.sendStanza(newMessage);

			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class SendGroupAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			Message newMessage = new Message();
			newMessage.setType(Message.Type.groupchat);
			newMessage.setBody(txtChat.getText());

			try {
				newMessage.setTo(JidCreate.entityBareFrom(txtGroup.getText() + "@conference." + txtDomain.getText()));
				newMessage.setFrom(JidCreate.entityBareFrom(txtName.getText() + "@" + txtDomain.getText()));

				xmppCnn.sendStanza(newMessage);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class CreateRoomAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// Get the MultiUserChatManager
			MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(xmppCnn);

			try {
				// Create the XMPP address (JID) of the MUC.
				EntityBareJid mucJid = (EntityBareJid) JidCreate
						.bareFrom(txtGroup.getText() + "@conference." + txtDomain.getText());
				// Create the nickname.
				Resourcepart nickname = Resourcepart.from(txtName.getText());

				// Create a MultiUserChat using an XMPPConnection for a room
				MultiUserChat muc = manager.getMultiUserChat(mucJid);

				// Prepare a list of owners of the new room
//				Set<Jid> owners = JidUtil.jidSetFrom(new String[] { "me@example.org", "juliet@example.org" });

				// Create the room
				/*
				 * muc.create(nickname) .getConfigFormManager() .submitConfigurationForm();
				 */

				muc.create(nickname);

				// Set the answer form
				Form configForm = muc.getConfigurationForm();
				Form answerForm = configForm.createAnswerForm();

				// Add the default answers to the form to submit
				for (FormField field : configForm.getFields()) {
					if (field.getType() == FormField.Type.hidden || StringUtils.isNullOrEmpty(field.getVariable())) {
						continue;
					}
					answerForm.setDefaultAnswer(field.getVariable());
				}

				// Sets the new owner of the room
				List<String> owners = new ArrayList<String>();
				owners.add(txtName.getText() + "@" + txtDomain.getText());
				answerForm.setAnswer("muc#roomconfig_roomowners", owners);
				answerForm.setAnswer("muc#roomconfig_persistentroom", true);
				answerForm.setAnswer("muc#roomconfig_membersonly", true);
				answerForm.setAnswer("muc#roomconfig_allowinvites", true);
				answerForm.setAnswer("muc#roomconfig_changesubject", true);

				// Send the completed form (with default values) to the server to
				// configure the room
				muc.sendConfigurationForm(answerForm);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class PresenceRoomAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// Get the MultiUserChatManager
			MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(xmppCnn);

			try {
				// Create the XMPP address (JID) of the MUC.
				EntityBareJid mucJid = (EntityBareJid) JidCreate
						.bareFrom(txtGroup.getText() + "@conference." + txtDomain.getText());

				// Create a MultiUserChat using an XMPPConnection for a room
				MultiUserChat muc = manager.getMultiUserChat(mucJid);

				Resourcepart nickname = Resourcepart.from(txtName.getText());
				muc.join(nickname);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class ChangeNickAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// Get the MultiUserChatManager
			MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(xmppCnn);

			try {
				// Create the XMPP address (JID) of the MUC.
				EntityBareJid mucJid = (EntityBareJid) JidCreate
						.bareFrom(txtGroup.getText() + "@conference." + txtDomain.getText());

				// Create a MultiUserChat using an XMPPConnection for a room
				MultiUserChat muc = manager.getMultiUserChat(mucJid);

				// Create the nickname.
				Resourcepart nickname = Resourcepart.from(txtName.getText());
				muc.join(nickname);
				muc.changeNickname(nickname);
				;
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class GetJoinedRoomsAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// Get the MultiUserChatManager
			MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(xmppCnn);

			try {
				// Create the XMPP address (JID) of the MUC.
				EntityBareJid mucJid = (EntityBareJid) JidCreate
						.bareFrom(txtGroup.getText() + "@conference." + txtDomain.getText());

				// Create a MultiUserChat using an XMPPConnection for a room
				MultiUserChat muc = manager.getMultiUserChat(mucJid);

				// Get the rooms where the user has joined
				Set<EntityBareJid> joinedRooms = manager.getJoinedRooms();

				log(joinedRooms.toString());
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class DestoryRoomAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			// Get the MultiUserChatManager
			MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(xmppCnn);

			try {
				// Create the XMPP address (JID) of the MUC.
				EntityBareJid mucJid = (EntityBareJid) JidCreate
						.bareFrom(txtGroup.getText() + "@conference." + txtDomain.getText());

				// Create a MultiUserChat using an XMPPConnection for a room
				MultiUserChat muc = manager.getMultiUserChat(mucJid);

				muc.destroy("", mucJid);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class FinAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			Fin packet = new Fin();
			packet.setVersion(Long.parseLong(txtChat.getText()));
			log("FIN = " + packet.toXML());

			try {
				xmppCnn.sendStanza(packet);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class SetTokenAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			APNSToken packet = new APNSToken();
			packet.setId(txtChat.getText());

			try {
				xmppCnn.sendStanza(packet);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class CancelAPNSAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			CancelAPNS packet = new CancelAPNS();

			try {
				xmppCnn.sendStanza(packet);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class ClearAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			txtMsg.setText("");
		}
	}

	class IncomeingPacketListener implements StanzaListener {
		public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
			log("RCVD: " + packet.toXML());

			if (packet instanceof Message) {
				Message msg = (Message) packet;
//        		ExtensionElement elmt = msg.getExtension("receipt", "fc:msg:srv");
//        		if(elmt != null){
//                	log("ExtensionElement: " + elmt.toXML());
//        		}    		
				List<ExtensionElement> extList = msg.getExtensions();
				if (extList != null && !extList.isEmpty()) {
					for (ExtensionElement extElement : extList) {
						log("ExtensionElement: " + extElement.getElementName() + " " + extElement.getNamespace());
						log("ExtensionElement XML: " + extElement.toXML());
					}
				}

				if (msg.getType().equals(Message.Type.error)) {
					XMPPError err = msg.getError();
					if (err != null) {
						log("ERROR CODE = " + err.getCode());
					}
				}
			} else if (packet instanceof IQ) {
				if (packet instanceof OMAmount) {
					OMAmount omAmount = (OMAmount) packet;
					log("OMAmount: " + packet.toXML() + "， amount = " + omAmount.getAmount());
				} else if (packet instanceof OfflineMessageItems) {
					OfflineMessageItems items = (OfflineMessageItems) packet;
					log("items count = " + items.getCount());
					for (Message msg : items.getOfflineMessageItems()) {
						log(msg.toXML().toString());
					}
				}
			}
		}
	}

	class OutcomingPacketInterceptor implements StanzaListener {
		public void processStanza(Stanza packet) throws NotConnectedException, InterruptedException {
			log("SEND: " + packet.toXML().toString());
		}
	}

	class OmAmountAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			OfflineMsgAmount packet = new OfflineMsgAmount();

			try {
				xmppCnn.sendStanza(packet);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class OmPageAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			OfflineMsgPage packet = new OfflineMsgPage();
			packet.setLimit("10");
			packet.setVersion(txtChat.getText());

			try {
				xmppCnn.sendStanza(packet);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class SetupDisturberAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			Disturber packet = new Disturber();
			packet.setActoin(Disturber.ATTR_ACTION_SETUP);

			// for user
//			packet.setItemType(Disturber.ATTR_TYPE_USER);
//			packet.setJid(txtTo.getText() + "." + txtDomain.getText());

			// for room
			packet.setItemType(Disturber.ATTR_TYPE_ROOM);
			packet.setJid(txtGroup.getText() + "@conference." + txtDomain.getText());

			try {
				xmppCnn.sendStanza(packet);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class CancelDisturberAction implements ActionListener {

		public void actionPerformed(ActionEvent e) {
			Disturber packet = new Disturber();
//			packet.setItemType(Disturber.ATTR_TYPE_USER);
			packet.setActoin(Disturber.ATTR_ACTION_CANCEL);
			packet.setJid(txtTo.getText() + "@" + txtDomain.getText());

			try {
				xmppCnn.sendStanza(packet);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class GetDisturberListAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			Disturber packet = new Disturber();
			packet.setType(IQ.Type.get);

			try {
				xmppCnn.sendStanza(packet);
			} catch (Exception e1) {
				e1.printStackTrace();
				log(e1.getMessage());
			}
		}
	}

	class AddFriendAction implements ActionListener {
		public void actionPerformed(ActionEvent e) {

			// Create and send roster entry creation packet.
//	        RosterPacket rosterPacket = new RosterPacket();
//	        rosterPacket.setType(IQ.Type.set);
//	        RosterPacket.Item item = new RosterPacket.Item(user, name);
//	        if (groups != null) {
//	            for (String group : groups) {
//	                if (group != null && group.trim().length() > 0) {
//	                    item.addGroupName(group);
//	                }
//	            }
//	        }
//	        rosterPacket.addRosterItem(item);
//	        xmppCnn.createStanzaCollectorAndSend(rosterPacket).nextResultOrThrow();

			try {
				Presence subscribe = new Presence(Presence.Type.subscribe);
				Jid to = JidCreate.bareFrom(txtTo.getText() + "@" + txtDomain.getText());
				subscribe.setTo(to);

				xmppCnn.sendStanza(subscribe);
			} catch (Exception e1) {
				log(e1.getMessage());
			}
		}
	}
}
